package com.reactim.message.performance;

import com.reactim.message.metrics.ConnectionPerformanceMetrics;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 性能优化分析器
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PerformanceOptimizer {

    private final ConnectionPerformanceMetrics performanceMetrics;

    /**
     * 分析性能瓶颈并提供优化建议
     */
    public OptimizationReport analyzePerformance() {
        log.info("开始分析性能瓶颈...");
        
        ConnectionPerformanceMetrics.PerformanceReport report = performanceMetrics.getPerformanceReport();
        List<PerformanceIssue> issues = new ArrayList<>();
        List<OptimizationRecommendation> recommendations = new ArrayList<>();
        
        // 分析存储操作性能
        analyzeStorePerformance(report, issues, recommendations);
        
        // 分析检索操作性能
        analyzeRetrievePerformance(report, issues, recommendations);
        
        // 分析错误率
        analyzeErrorRates(report, issues, recommendations);
        
        // 分析延迟分布
        analyzeLatencyDistribution(report, issues, recommendations);
        
        // 分析连接管理效率
        analyzeConnectionManagement(report, issues, recommendations);
        
        OptimizationReport optimizationReport = OptimizationReport.builder()
                .performanceReport(report)
                .issues(issues)
                .recommendations(recommendations)
                .overallScore(calculateOverallScore(issues))
                .build();
        
        log.info("性能分析完成，发现 {} 个问题，提供 {} 条建议", 
                issues.size(), recommendations.size());
        
        return optimizationReport;
    }

    /**
     * 分析存储操作性能
     */
    private void analyzeStorePerformance(ConnectionPerformanceMetrics.PerformanceReport report,
                                       List<PerformanceIssue> issues,
                                       List<OptimizationRecommendation> recommendations) {
        
        // 检查平均存储时间
        if (report.getAverageStoreTime() > 100) { // 超过100ms
            issues.add(PerformanceIssue.builder()
                    .severity(Severity.HIGH)
                    .category("存储性能")
                    .description(String.format("存储操作平均耗时过长: %.2f ms", report.getAverageStoreTime()))
                    .impact("影响用户连接建立速度")
                    .build());
            
            recommendations.add(OptimizationRecommendation.builder()
                    .priority(Priority.HIGH)
                    .category("存储优化")
                    .title("优化Redis存储性能")
                    .description("考虑以下优化措施：1) 启用Redis管道操作 2) 优化序列化方式 3) 调整连接池配置")
                    .expectedImprovement("预期可将存储时间降低30-50%")
                    .build());
        }
        
        // 检查P99延迟
        if (report.getStoreLatencyP99() > 500) { // P99超过500ms
            issues.add(PerformanceIssue.builder()
                    .severity(Severity.MEDIUM)
                    .category("存储性能")
                    .description(String.format("存储操作P99延迟过高: %.2f ms", report.getStoreLatencyP99()))
                    .impact("部分用户体验较差的连接延迟")
                    .build());
            
            recommendations.add(OptimizationRecommendation.builder()
                    .priority(Priority.MEDIUM)
                    .category("延迟优化")
                    .title("优化长尾延迟")
                    .description("实施超时控制和重试机制，考虑使用本地缓存作为降级方案")
                    .expectedImprovement("预期可将P99延迟降低至200ms以下")
                    .build());
        }
    }

    /**
     * 分析检索操作性能
     */
    private void analyzeRetrievePerformance(ConnectionPerformanceMetrics.PerformanceReport report,
                                          List<PerformanceIssue> issues,
                                          List<OptimizationRecommendation> recommendations) {
        
        // 检查平均检索时间
        if (report.getAverageRetrieveTime() > 50) { // 超过50ms
            issues.add(PerformanceIssue.builder()
                    .severity(Severity.MEDIUM)
                    .category("检索性能")
                    .description(String.format("检索操作平均耗时过长: %.2f ms", report.getAverageRetrieveTime()))
                    .impact("影响消息推送效率")
                    .build());
            
            recommendations.add(OptimizationRecommendation.builder()
                    .priority(Priority.MEDIUM)
                    .category("缓存优化")
                    .title("增强本地缓存策略")
                    .description("增加本地缓存命中率，实施智能预加载策略")
                    .expectedImprovement("预期可将检索时间降低60-80%")
                    .build());
        }
        
        // 检查检索与存储的比例
        double retrieveStoreRatio = report.getRetrieveOperationCount() / Math.max(report.getStoreOperationCount(), 1);
        if (retrieveStoreRatio > 10) { // 检索操作远多于存储操作
            recommendations.add(OptimizationRecommendation.builder()
                    .priority(Priority.HIGH)
                    .category("缓存策略")
                    .title("优化缓存策略")
                    .description(String.format("检索/存储比例为 %.1f:1，建议增强缓存策略", retrieveStoreRatio))
                    .expectedImprovement("通过缓存可显著减少Redis访问次数")
                    .build());
        }
    }

    /**
     * 分析错误率
     */
    private void analyzeErrorRates(ConnectionPerformanceMetrics.PerformanceReport report,
                                 List<PerformanceIssue> issues,
                                 List<OptimizationRecommendation> recommendations) {
        
        // 计算存储错误率
        double storeErrorRate = report.getStoreErrorCount() / Math.max(report.getStoreOperationCount(), 1) * 100;
        if (storeErrorRate > 1) { // 错误率超过1%
            issues.add(PerformanceIssue.builder()
                    .severity(Severity.HIGH)
                    .category("可靠性")
                    .description(String.format("存储操作错误率过高: %.2f%%", storeErrorRate))
                    .impact("影响系统稳定性和用户体验")
                    .build());
            
            recommendations.add(OptimizationRecommendation.builder()
                    .priority(Priority.HIGH)
                    .category("可靠性优化")
                    .title("增强错误处理和重试机制")
                    .description("实施指数退避重试策略，增加熔断器保护")
                    .expectedImprovement("预期可将错误率降低至0.1%以下")
                    .build());
        }
        
        // 计算检索错误率
        double retrieveErrorRate = report.getRetrieveErrorCount() / Math.max(report.getRetrieveOperationCount(), 1) * 100;
        if (retrieveErrorRate > 0.5) { // 错误率超过0.5%
            issues.add(PerformanceIssue.builder()
                    .severity(Severity.MEDIUM)
                    .category("可靠性")
                    .description(String.format("检索操作错误率偏高: %.2f%%", retrieveErrorRate))
                    .impact("可能导致消息推送失败")
                    .build());
        }
    }

    /**
     * 分析延迟分布
     */
    private void analyzeLatencyDistribution(ConnectionPerformanceMetrics.PerformanceReport report,
                                          List<PerformanceIssue> issues,
                                          List<OptimizationRecommendation> recommendations) {
        
        // 检查延迟分布的均匀性
        double storeLatencySpread = report.getStoreLatencyP99() - report.getStoreLatencyP50();
        if (storeLatencySpread > 200) { // P99和P50差距超过200ms
            issues.add(PerformanceIssue.builder()
                    .severity(Severity.MEDIUM)
                    .category("性能一致性")
                    .description(String.format("存储延迟分布不均匀，P99-P50差距: %.2f ms", storeLatencySpread))
                    .impact("用户体验不一致")
                    .build());
            
            recommendations.add(OptimizationRecommendation.builder()
                    .priority(Priority.MEDIUM)
                    .category("性能调优")
                    .title("优化性能一致性")
                    .description("调整连接池配置，实施负载均衡策略")
                    .expectedImprovement("预期可将延迟分布差距缩小至100ms以内")
                    .build());
        }
    }

    /**
     * 分析连接管理效率
     */
    private void analyzeConnectionManagement(ConnectionPerformanceMetrics.PerformanceReport report,
                                           List<PerformanceIssue> issues,
                                           List<OptimizationRecommendation> recommendations) {
        
        // 检查连接泄漏
        long netConnections = report.getTotalConnectionsCreated() - report.getTotalConnectionsRemoved();
        if (netConnections > report.getCurrentConnections() * 1.1) { // 净连接数明显大于当前连接数
            issues.add(PerformanceIssue.builder()
                    .severity(Severity.HIGH)
                    .category("资源管理")
                    .description("可能存在连接泄漏问题")
                    .impact("内存和资源浪费")
                    .build());
            
            recommendations.add(OptimizationRecommendation.builder()
                    .priority(Priority.HIGH)
                    .category("资源管理")
                    .title("增强连接生命周期管理")
                    .description("实施定期清理机制，增加连接超时检测")
                    .expectedImprovement("预期可减少资源占用20-30%")
                    .build());
        }
        
        // 检查在线统计性能
        if (report.getAverageOnlineCountTime() > 100) { // 超过100ms
            issues.add(PerformanceIssue.builder()
                    .severity(Severity.LOW)
                    .category("统计性能")
                    .description(String.format("在线用户统计耗时过长: %.2f ms", report.getAverageOnlineCountTime()))
                    .impact("影响监控和统计功能")
                    .build());
            
            recommendations.add(OptimizationRecommendation.builder()
                    .priority(Priority.LOW)
                    .category("统计优化")
                    .title("优化统计查询")
                    .description("使用缓存存储统计结果，定期更新")
                    .expectedImprovement("预期可将统计时间降低至10ms以下")
                    .build());
        }
    }

    /**
     * 计算总体性能评分
     */
    private int calculateOverallScore(List<PerformanceIssue> issues) {
        int baseScore = 100;
        
        for (PerformanceIssue issue : issues) {
            switch (issue.getSeverity()) {
                case HIGH:
                    baseScore -= 20;
                    break;
                case MEDIUM:
                    baseScore -= 10;
                    break;
                case LOW:
                    baseScore -= 5;
                    break;
            }
        }
        
        return Math.max(baseScore, 0);
    }

    // 数据结构定义
    @lombok.Data
    @lombok.Builder
    public static class OptimizationReport {
        private ConnectionPerformanceMetrics.PerformanceReport performanceReport;
        private List<PerformanceIssue> issues;
        private List<OptimizationRecommendation> recommendations;
        private int overallScore;
        
        public String generateSummary() {
            StringBuilder summary = new StringBuilder();
            summary.append("=== 性能优化分析报告 ===\n");
            summary.append(String.format("总体评分: %d/100\n", overallScore));
            summary.append(String.format("发现问题: %d 个\n", issues.size()));
            summary.append(String.format("优化建议: %d 条\n", recommendations.size()));
            
            if (!issues.isEmpty()) {
                summary.append("\n主要问题:\n");
                issues.stream()
                    .filter(issue -> issue.getSeverity() == Severity.HIGH)
                    .forEach(issue -> summary.append(String.format("- [高] %s: %s\n", 
                        issue.getCategory(), issue.getDescription())));
            }
            
            if (!recommendations.isEmpty()) {
                summary.append("\n优先建议:\n");
                recommendations.stream()
                    .filter(rec -> rec.getPriority() == Priority.HIGH)
                    .forEach(rec -> summary.append(String.format("- %s: %s\n", 
                        rec.getTitle(), rec.getDescription())));
            }
            
            return summary.toString();
        }
    }

    @lombok.Data
    @lombok.Builder
    public static class PerformanceIssue {
        private Severity severity;
        private String category;
        private String description;
        private String impact;
    }

    @lombok.Data
    @lombok.Builder
    public static class OptimizationRecommendation {
        private Priority priority;
        private String category;
        private String title;
        private String description;
        private String expectedImprovement;
    }

    public enum Severity {
        HIGH, MEDIUM, LOW
    }

    public enum Priority {
        HIGH, MEDIUM, LOW
    }
}